from player import *
from level import *
from game import *
from constants import *
from os import listdir, sep

from glyph import Glyph, Editor, Macros

class Menu:
	"""Allows the user to create either a new game, load a previous one or save the current one.
	-- Class variables --
	isRunning        : boolean : Condition for the main loop to run.
	currentSelection : integer : Index of the current choice in the menu.
	window           : Pygame  : Main window of the game.
	background       : Pygame  : Image representing the background of the menu.
	newGameText      : Pygame  : Image representing the item "New Game" in the menu.
	loadGameText     : Pygame  : Image representing the item "Load Game" in the menu.
	cursor           : Pygame  : Image representing the cursor in the menu.
	game             : Game    : The current Game.
	-- Class public methods --
	run               : None    : Main loop of the menu.
	createNewGame     : None    : Creates a new game interactively.
	createNewSavefile : string  : Return the next filename available to save a new game.
	loadGame          : None    : Loads a previous game interactively.
	loadName          : string  : Imports the name of the character. Returns the line following the name section.
	loadLevel         : strig   : Imports the filename of the level to load. Returns the line following the level section.
	loadPosition      : string  : Imports the position of the character. Returns the line following the position section.
	"""
	def __init__(self, window):
		self.isRunning = True
		self.currentSelection = 0 
		self.window = window
		self.background = pygame.image.load(MenuBackground).convert_alpha()
		self.newGameText = pygame.image.load(NewGameSprite).convert_alpha()
		self.loadGameText = pygame.image.load(LoadGameSprite).convert_alpha()
		self.quitGameText = pygame.image.load(QuitGameSprite).convert_alpha()
		self.cursor = pygame.image.load(CursorSprite).convert_alpha()
		self.yourNameText = None
		self.editor = None
		self.game = None

	def run(self):
		"""Runs the menu main loop.
		-- Inputs --
		None
		-- Outputs --
		None
		"""
		while (self.isRunning):
			pygame.time.Clock().tick(Delay)
			self.window.blit(self.background,(0,0))
			self.window.blit(self.newGameText,(MainMenuXPosition,MainMenuItemsYPositions[0]))
			self.window.blit(self.loadGameText,(MainMenuXPosition,MainMenuItemsYPositions[1]))
			self.window.blit(self.quitGameText,(MainMenuXPosition,MainMenuItemsYPositions[2]))
			self.window.blit(self.cursor,(MainMenuCursorXPosition,MainMenuItemsYPositions[self.currentSelection]))
			pygame.display.flip()
			for event in pygame.event.get():
				# Quitter le jeu
				if ((event.type == QUIT) or (event.type == KEYDOWN and event.key == K_ESCAPE)):
					self.isRunning = False
				elif (event.type == KEYDOWN and event.key == K_DOWN):
					self.currentSelection = (self.currentSelection + 1)%len(MainMenuItemsYPositions)
				elif (event.type == KEYDOWN and event.key == K_UP):
					self.currentSelection = (self.currentSelection - 1)%len(MainMenuItemsYPositions)
				elif (event.type == KEYDOWN and event.key == K_RETURN):
					if (self.currentSelection == 0):
						self.createNewGame()
					elif (self.currentSelection == 1):
						self.loadGame()
					elif (self.currentSelection == 2):
						self.isRunning = False
						break
					if (self.game):
						self.game.run()
						self.game = None
		return

	def createNewGame(self):
		"""Interactive method creating a game with the appropriate parameters.
		-- Inputs --
		None
		-- Outputs --
		None
		"""
		name = self.setAvatarName()
		if (name):
			player = Player(name)
			savefile = self.createNewSavefile()
			self.game = Game(player, BeginningLevel, savefile, self.window)
		return

	def setAvatarName(self):
		"""Interactive method allowing to type the avatar's name.
		-- Input --
		None
		-- Output --
		name     : string   : Name of the new avatar
		"""
		self.yourNameText = pygame.image.load(YourNameSprite).convert_alpha()
		self.editor = Editor(CLIP, [' '],**DEFAULT)
		editor_rect = self.editor.rect
		pygame.time.Clock().tick(Delay)
		self.window.blit(self.background,(0,0))
		self.window.blit(self.yourNameText, (NewGameMenuItemXPosition, NewGameMenuItemYPosition))
		self.window.blit(self.editor.image, editor_rect)
		pygame.display.flip()

		while (True):
			for event in pygame.event.get():
				if (event.type == KEYDOWN and event.key == K_RETURN):
					if (len(self.editor.txt) > 1):
						return ''.join(self.editor.txt[:-1])
				elif (event.type == KEYDOWN and len(self.editor.txt) < NameMaxLength+1 and (event.key in AlphaNumericChars)):
					self.editor.input(event)
				elif (event.type ==  KEYDOWN and event.key == K_BACKSPACE and len(self.editor.txt) > 1 ):
					self.editor.input(event)
				elif (event.type == KEYDOWN and event.key == K_ESCAPE):
					return None
				else:
					pass
			cursor = self.editor.get_cursor()
			self.editor.image.fill((255, 205, 0), cursor)
			self.window.blit(self.editor.image, editor_rect)
			pygame.display.update()

	def createNewSavefile(self):
		"""Generates the next possible filename to save the new game.
		-- Inputs --
		None
		-- Outputs --
		savefileName   : string  : Name of the file associated with the current game.
		"""
		savefiles = listdir(CharsDirectory)
		index = 1
		savefileName = "%s%i%s"%(SavefileBasename, index, SavefileExtension)
		while (savefileName in savefiles):
			index += 1
			savefileName = "%s%i%s"%(SavefileBasename, index, SavefileExtension)
		return savefileName

	def loadGame(self):
		"""Interactive method allowing to select a previously saved game.
		-- Inputs --
		None
		-- Outputs --
		None
		"""
		# Select the file to load
		savefile = self.selectSavefile()
		f = open('%s%s%s'%(CharsDirectory, os.sep, savefile))
		line = f.readline().strip()
		while (line != ''):
			if (line == FileNameSection):
				(name, line) = self.loadName(f)
			elif (line == FileLevelSection):
				(levelfile, line) = self.loadLevel(f)
				levelfile = '%s%s%s'%(MapsDirectory, os.sep, levelfile)
			elif (line == FilePositionSection):
				(position, line) = self.loadPosition(f)
			else :
				line = f.readline().strip()
		# Initializes the player.
		player = Player(name)
		player.x = position[0]
		player.y = position[1]
		self.game = Game(player, levelfile, savefile, self.window)
		f.close()
		return

	def selectSavefile(self):
		"""Menu allowing the user to select one of the available savefiles.
		-- Inputs --
		None
		-- Outputs --
		savefile     : string   : The name of the file to load.
		"""
		# Code under development:
		files = listdir(CharsDirectory)
		savefiles = []
		for f in files :
			if (f[:5] == SavefileBasename): # takes off the .svn item from the list.
				savefiles.append(f)
		# Temporary code:
		savefile = raw_input('Savefile basename (without extension): ') # TO DO: this should be the savefile selected.
		savefile = '%s%s'%(savefile, SavefileExtension) 
		return savefile

	def loadName(self, f):
		"""Returns the name of the character.
		-- Inputs --
		f           : stream   : The file stream.
		-- Outputs --
		name        : string   : The name of the character.
		line        : string   : The line following the /Name section.
		"""
		line = f.readline().strip()
		name = line
		line = f.readline().strip()
		return (name, line)

	def loadLevel(self, f):
		""" Returns the filename of the level to load.
		-- Inputs --
		f           : stream   : The file stream.
		-- Outputs --
		levelfile   : string   : The filename of the level to load.
		line        : string   : The line following the /Name section.
		"""
		line = f.readline().strip()
		levelfile = line
		line = f.readline().strip()
		return (levelfile, line)

	def loadPosition(self, f):
		"""Returns the position (x,y) of the character to load.
		-- Inputs --
		f           : stream   : The file stream.
		-- Outputs --
		position    : tuple    : The position (x,y) of the character to load.
		line        : string   : The line following the /Name section.
		"""
		line = f.readline().strip().split('\t')
		position = (int(line[0]), int(line[1]))
		return (position, line)

pygame.font.init()

#glyph constants
CLIP = Rect(0, 0, 320, 80)
CLIP.center = (WindowDefaultWidth/2, WindowDefaultHeigth*9/12)

FONT = pygame.font.Font("texts%ssilkscreen.ttf"%(os.sep), 24)
DEFAULT = {
	'bkg'       : (15, 15, 15),
	'color'     : (201, 192, 187),
	'font'      : FONT,
	'spacing'   : FONT.get_linesize(),
}


